﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Panels
{
    public class ScrambledMultiColumnStackPanel : MultiColumnStackPanel
    {
        #region Fields

        private Random random = new Random();

        #endregion Fields
        #region Constructors

        public ScrambledMultiColumnStackPanel()
            : base()
        {
            MinAngle = -20;
            MaxAngle = 20;
        }

        #endregion Constructors
        #region Properties

        public static readonly DependencyProperty MinAngleProperty = DependencyProperty.Register("MinAngle", typeof(int), typeof(ScrambledMultiColumnStackPanel), new PropertyMetadata(OnMinAnglePropertyChanged));
        public int MinAngle
        {
            get { return (int)GetValue(MinAngleProperty); }
            set { SetValue(MinAngleProperty, value); }
        }

        private static void OnMinAnglePropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            ScrambledMultiColumnStackPanel panel = sender as ScrambledMultiColumnStackPanel;
            if (panel != null)
            {
                panel.NotifyPropertyChanged("MinAngle");
            }
        }

        public static readonly DependencyProperty MaxAngleProperty = DependencyProperty.Register("MaxAngle", typeof(int), typeof(ScrambledMultiColumnStackPanel), new PropertyMetadata(OnMaxAnglePropertyChanged));
        public int MaxAngle
        {
            get { return (int)GetValue(MaxAngleProperty); }
            set { SetValue(MaxAngleProperty, value); }
        }

        private static void OnMaxAnglePropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            ScrambledMultiColumnStackPanel panel = sender as ScrambledMultiColumnStackPanel;
            if (panel != null)
            {
                panel.NotifyPropertyChanged("MaxAngle");
            }
        }

        #endregion Properties

        protected override Size ArrangeOverride(Size finalSize)
        {
            int column = 0;
            Point position = new Point(0.0, 0.0);
            Size rowSize = new Size();
            rowSize.Width = finalSize.Width / Columns;

            foreach (UIElement child in this.Children)
            {
                Size childSize = child.DesiredSize;

                childSize.Width = rowSize.Width;
                child.Arrange(new Rect(position.X, position.Y, childSize.Width, childSize.Height));

                RotateTransform rotation = GetRotateTransform(child);
                rotation.Angle = random.Next(MinAngle, MaxAngle);

                position.X += childSize.Width;
                rowSize.Height = Math.Max(childSize.Height, rowSize.Height);
                column++;                

                if (column >= Columns)
                {
                    position.Y += rowSize.Height;

                    position.X = 0.0;
                    rowSize.Height = 0.0;
                    column = 0;
                }
            }

            return finalSize;
        }

        private RotateTransform GetRotateTransform(UIElement element)
        {            
            RotateTransform rotation = null;

            rotation = element.RenderTransform as RotateTransform;
            if (rotation != null)
            {
                return rotation;
            }

            TransformGroup group = element.RenderTransform as TransformGroup;
            if(group != null)
            {
                foreach (Transform t in group.Children)
                {
                    rotation = t as RotateTransform;
                    if (rotation != null)
                    {
                        return rotation;
                    }
                }

                rotation = new RotateTransform();
                group.Children.Add(rotation);

                return rotation;
            }

            rotation = new RotateTransform();
            element.RenderTransform = rotation;
            element.RenderTransformOrigin = new Point(0.5, 0.5);

            return rotation;        
        }

    }
}
